/**
 * 桥接模式:可将一个大类或一系列紧密相关的类拆分为抽象和实现两个独立的层次结构，从而能在开发时分别使用。
 * 以下情形考虑使用桥接模式：
    1. 如果想要拆分或重组一个具有多重功能的庞杂类（例如能与多个数据库服务器进行交互的类），可以使用桥接模式。
    类的代码行数越多，弄清其运作方式就越困难，对其进行修改所花费的时间就越长。一个功能上的变化可能需要在整个类范围内进行修改，而且常常会产生错误，甚至还会有一些严重的副作用。
    桥接模式可以将庞杂类拆分为几个类层次结构。此后，可以修改任意一个类层次结构而不会影响到其他类层次结构。这种方法可以简化代码的维护工作，并将修改已有代码的风险降到最低。
    2. 如果希望在几个独立维度上扩展一个类，可使用该模式。
    桥接建议将每个维度抽取为独立的类层次。初始类将相关工作委派给属于对应类层次的对象，无需自己完成所有工作。
    3. 如果需要在运行时切换不同实现方法，可使用桥接模式。
    当然并不是说一定要实现这一点，桥接模式可替换抽象部分中的实现对象，具体操作就和给成员变量赋新值一样简单。
    顺便提一句， 最后一点是很多人混淆桥接模式和策略模式的主要原因。记住，设计模式并不仅是一种对类进行组织的方式，它还能用于沟通意图和解决问题。

   优点：
    1. 将实现抽离出来，再实现抽象，使得对象的具体实现依赖于抽象，满足了依赖倒转原则。
    2. 更好的可扩展性。
    3. 可动态的切换实现。桥接模式实现了抽象和实现的分离，在实现桥接模式时，就可以实现动态的选择具体的实现。
 */
#pragma once

#include <iostream>
#include <memory>

using namespace std;

namespace bridge
{
//抽象App类，提供接口
class App
{
public:
    virtual ~App() { cout << "~App()" << endl; }
    virtual void run() = 0;
};
//具体的App实现类
class GameApp : public App
{
public:
    void run() {
        cout << "GameApp Running" << endl;
    }
};
//具体的App实现类
class TranslateApp : public App
{
public:
    void run() {
        cout << "TranslateApp Running" << endl;
    }
};
//抽象手机类，提供接口
class MobilePhone
{
public:
    virtual ~MobilePhone() { cout << "~MobilePhone()" << endl;}
    virtual void appRun(App* app) = 0;  //实现App与手机的桥接
};
//具体的手机实现类
class XiaoMi : public MobilePhone
{
public:
    void appRun(App* app) {
        cout << "XiaoMi: ";
        app->run();
    }
};
//具体的手机实现类
class HuaWei : public MobilePhone
{
public:
    void appRun(App* app) {
        cout << "HuaWei: ";
        app->run();
    }
};

void ClientCode()
{
    unique_ptr<App> gameApp(new GameApp);
    unique_ptr<App> translateApp(new TranslateApp);
    unique_ptr<MobilePhone> xiaomi(new XiaoMi);
    unique_ptr<MobilePhone> huawei(new HuaWei);
    xiaomi->appRun(gameApp.get());
    xiaomi->appRun(translateApp.get());
    huawei->appRun(gameApp.get());
    huawei->appRun(translateApp.get());
}
} // namespace bridge
